/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.web.gwt.form.client.widget.item.impl;

import java.util.Date;

import com.genia.toolbox.web.gwt.basics.client.GwtHelper;
import com.genia.toolbox.web.gwt.basics.client.i18n.GwtI18nMessage;
import com.genia.toolbox.web.gwt.basics.client.widget.AbstractDateChooser;
import com.genia.toolbox.web.gwt.form.client.CssNames;
import com.genia.toolbox.web.gwt.form.client.form.AbstractPeriodItem;
import com.genia.toolbox.web.gwt.form.client.message.Messages;
import com.genia.toolbox.web.gwt.form.client.widget.item.ItemWidgetModifyListener;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * {@link com.genia.toolbox.web.gwt.form.client.widget.item.SimpleItemWidget}
 * representing the different kind of date.
 * 
 * @param <ITEM>
 *          the type of item handled by this widget.
 */
public abstract class AbstractPeriodItemWidget<ITEM extends AbstractPeriodItem>
    extends AbstractSimpleValuedItemWidget<ITEM>
{

  /**
   * the base widget of this component.
   */
  private final transient Panel panel = new HorizontalPanel();

  /**
   * the widgets that the setErrorMessage must modify.
   */
  private final transient Widget[] widgetsToToggle;

  /**
   * {@link CheckBox} allowing to return a <code>null</code> value.
   */
  private final transient CheckBox isNullCheckbox;

  /**
   * the widget to choose the date.
   */
  protected transient final AbstractDateChooser abstractDateChooser;

  /**
   * panel displayed when no date is selected.
   */
  private transient final Panel noDatePanel;

  /**
   * {@link ClickListener} to handle disabling the date.
   */
  private transient final ClickListener isNullCheckboxClickListener = new ClickListener()
  {

    public void onClick(Widget sender)
    {
      updateDisplay();
    }

  };



  /**
   * constructor.
   * 
   * @param item
   *          the item this object represents
   * @param abstractDateChooser
   *          the widget to choose the date
   * @param widgetStyleName
   *          the style name of this widget
   */
  protected AbstractPeriodItemWidget(final ITEM item, final AbstractDateChooser abstractDateChooser, final String widgetStyleName)
  {
    super(item);
    this.abstractDateChooser = abstractDateChooser;
    if (item.getNullable().booleanValue()) {
      isNullCheckbox = new CheckBox();
      isNullCheckbox.setChecked(true);
      GwtHelper.fillTitle(isNullCheckbox, Messages.DISABLE_DATE_MESSAGE);
      noDatePanel = new SimplePanel();
      noDatePanel.setVisible(false);
      noDatePanel.addStyleName(CssNames.DISABLED_DATE_WIDGET_CSS_STYLE);
      Label noDateLabel = new Label("----");
      noDatePanel.add(noDateLabel);
      isNullCheckbox.addClickListener(isNullCheckboxClickListener);
    }
    else {
      isNullCheckbox = null;
      noDatePanel = null;
    }

    Label label = new Label();
    // get properties from a DateItem.
    final GwtI18nMessage labelKey = item.getLabelKey();
    final boolean enableState = item.isEnabled();

    // get a DateItem Widget.
    GwtHelper.fillText(label, labelKey);

    panel.addStyleName(widgetStyleName);
    panel.addStyleName(item.getName());

    abstractDateChooser.setEnabled(enableState);
    panel.add(label);
    if (isNullCheckbox == null) {
      widgetsToToggle = new Widget[] { panel, (Widget) abstractDateChooser };
      panel.add((Widget) abstractDateChooser);
    }
    else {
      panel.add(noDatePanel);
      panel.add((Widget) abstractDateChooser);
      panel.add(isNullCheckbox);
      widgetsToToggle = new Widget[] { panel, (Widget) abstractDateChooser, noDatePanel };
    }

    initWidget(panel);
    setValue(String.valueOf(System.currentTimeMillis()));
  }



  /**
   * returns the current value of this item.
   * 
   * @return a <code>String</code> representing the current values of this item
   */
  @Override
  public String getValue()
  {
    if (isNullCheckbox != null && !isNullCheckbox.isChecked()) {
      return null;
    }
    return String.valueOf(abstractDateChooser.getValue().getTime());
  }



  /**
   * add a listener that is called each time the value of this object change.
   * 
   * @param modifyListener
   *          the callback
   */
  public void addModifyListener(final ItemWidgetModifyListener modifyListener)
  {
    abstractDateChooser.addChangeListener(new ChangeListener()
    {
      public void onChange(final Widget widget)
      {
        modifyListener.onModify(AbstractPeriodItemWidget.this);
      }
    });
    if (isNullCheckbox != null) {
      isNullCheckbox.addClickListener(new ClickListener()
      {
        public void onClick(final Widget widget)
        {
          modifyListener.onModify(AbstractPeriodItemWidget.this);
        }
      });
    }
  }



  /**
   * set the current value of this item.
   * 
   * @param value
   *          a <code>String</code> representing the new values of this item
   */
  @Override
  public void setValue(final String value)
  {
    Date d = null;
    if (value != null && !"".equals(value)) {
      d = new Date(Long.parseLong(value));
    }
    if (d == null) {
      if (isNullCheckbox == null) {
        abstractDateChooser.setValue(d);
      }
      else {
        isNullCheckbox.setChecked(false);
      }
    }
    else {
      if (isNullCheckbox != null) {
        isNullCheckbox.setChecked(true);
      }
      abstractDateChooser.setValue(d);
    }
    if (isNullCheckbox != null) {
      updateDisplay();
    }
  }



  /**
   * update the display of the widget if it is nullable.
   */
  private void updateDisplay()
  {
    noDatePanel.setVisible(!isNullCheckbox.isChecked());
    ((Widget) abstractDateChooser).setVisible(isNullCheckbox.isChecked());
  }



  /**
   * returns an array containing all the widgets that the setErrorMessage must
   * modify.
   * 
   * @return an array containing all the widgets that the setErrorMessage must
   *         modify
   */
  @Override
  protected Widget[] getWidgetsToToggle()
  {
    return widgetsToToggle;
  }

}
